-- RandomFactoryM
-- created by panyl
-- 随机数

module("RandomFactoryM", package.seeall);

local cursorTable = {};
local idMap = {};

-- 载入配置表
local _init = false;
local loadCsv = function()
    if _init then return end
    _init = true;

    cursorTable = {};
    idMap = {};
    local random_seed_cursor_CSV = get_random_seed_cursor_CSV();
    for _, row in pairs(random_seed_cursor_CSV) do
        cursorTable[row["type"]] = row;

        idMap[row.id] = row;
    end
end

-- 模块初始化操作
function init()
    loadCsv();
end

-- 偏移随机数
function shiftRandomCursor()
    local cursor = ME.user.dbase:query("randomCursor", {});
    local m = {};

    for id, value in pairs(cursor) do

        if idMap[id] then
            m[id] = value + idMap[id]["shift_offset"];
        else
            m[id] = value;
        end
    end

    ME.user.dbase:set("randomCursor", m);
end

function getRandomType(desc)
    -- 类型
    if not cursorTable[desc] then
        return "default:" .. desc;
    end

    return desc;
end

-- 获取随机数游标（暂时只有迷宫中用到，以后再说）
function fetchRandCursor(desc)
    local id = 0;
    if type(cursorTable[desc]) == "table" then
        id = cursorTable[desc].id;
    end
    local cursor = ME.user.dbase:query("randomCursor", {});

    return cursor[id] or 0;
end

-- 使用游标
function useRandCursor(desc, offset)
    local id = 0;
    if type(cursorTable[desc]) == "table" then
        id = cursorTable[desc].id;
    end
    local cursor = ME.user.dbase:query("randomCursor", {});
    ME.user.dbase:set("randomCursor", cursor);

    local value = (cursor[id] or 0) + (offset or 1);

    cursor[id] = bit.band(value, 0xffff);
end

-- 把随机数游标打包成字节
function packRandomCursor()
    local cursor = ME.user.dbase:query("randomCursor", {});
    local len = #table.keys(cursor);
    local buf = Buffer.create(4 * len);
    local index = 0;

    for id, value in pairs(cursor) do
        Buffer.set16(buf, 4 * index + 1, id);
        Buffer.set16(buf, 4 * index + 3, value);

        index = index + 1;
    end

    return buf;
end

-- 获取随机数，请确保服务器/客户端获取随机数操作的一致性
function myRandom(user)
    user = user or ME.user;

    local seed = user.dbase:query("random_seed");
    assert(type(seed) == "number");

    -- 随机数生成
    seed = genRand(seed);

    user.dbase:set("random_seed", seed);

    cclog("%s抽取随机数 %d", user:getName(), seed);

    return seed;
end

-- 生成一个随机数
function genRand(seed)
    local rand = seed * 214013 + 2531011;
    rand = bit.brshift(rand, 16);

    return bit.band(rand, 0x7fff);
end

-- 客户端的随机数.... 这个只能客户端有，服务器禁止
function genCommonRand(m, desc)
    local seed = ME.user.dbase:query("common_rand_seed");
    if not seed then
        seed = user.dbase:query("random_seed");
    end

    seed = genRand(seed);

    ME.user.dbase:set("common_rand_seed", seed);

    desc = desc or "";
    DungeonLogM.addLog(desc .. ":抽取通用随机数：" .. seed);

    if m and m > 0 then
        return seed % m + 1;
    end

    return seed;
end
